import http from '@ohos.net.http';
import promptAction from '@ohos.promptAction';
import media from '@ohos.multimedia.media';
import { BusinessError } from '@ohos.base';

// 自定义实现URLSearchParams，因为OpenHarmony不直接支持
class SimpleURLSearchParams {
  private params: Map<string, string> = new Map();

  append(key: string, value: string): void {
    this.params.set(key, value);
  }

  toString(): string {
    const parts: string[] = [];
    this.params.forEach((value, key) => {
      parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
    });
    return parts.join('&');
  }
}

// 响应类型定义
interface TtsResponse {
  success: boolean;
  audioUrl: string;
  textLength: number;
  message?: string;
}

/**
 * 语音合成工具类
 * 封装后端TTS API调用
 */
export default class TtsUtil {
  private static instance: TtsUtil;
  private readonly BASE_URL = 'http://192.168.0.6:9999';
  private avPlayer: media.AVPlayer | null = null;
  private isPlaying: boolean = false;
  private isInitializing: boolean = false;
  private initPromise: Promise<void> | null = null;
  private lastPlayedText: string = '';
  private lastPlayedTime: number = 0;
  private readonly RETRY_DELAY = 1000; // 重试延迟时间(毫秒)
  private readonly MAX_RETRIES = 3; // 最大重试次数
  private currentRetry: number = 0;
  
  // 单例模式
  private constructor() {
    // 初始化AVPlayer
    this.initPlayer();
  }

  public static getInstance(): TtsUtil {
    if (!TtsUtil.instance) {
      TtsUtil.instance = new TtsUtil();
    }
    return TtsUtil.instance;
  }

  // 初始化音频播放器
  private async initPlayer(): Promise<void> {
    // 如果已经在初始化中，返回现有的Promise
    if (this.isInitializing && this.initPromise) {
      return this.initPromise;
    }
    
    this.isInitializing = true;
    
    // 创建初始化Promise
    this.initPromise = new Promise<void>(async (resolve, reject) => {
      try {
        console.info('开始初始化AVPlayer');
        if (!this.avPlayer) {
          this.avPlayer = await media.createAVPlayer();
          console.info('AVPlayer创建成功');
          
          // 监听播放结束事件
          this.avPlayer.on('stateChange', (state: string) => {
            console.info(`AVPlayer状态变化: ${state}`);
            if (state === 'idle') {
              this.isPlaying = false;
            } else if (state === 'error') {
              console.error('AVPlayer发生错误');
              this.isPlaying = false;
              this.resetPlayer();
            }
          });
          
          console.info('AVPlayer事件监听设置完成');
        }
        this.isInitializing = false;
        resolve();
      } catch (error) {
        console.error('AVPlayer初始化失败:', error instanceof Error ? error.message : String(error));
        this.isInitializing = false;
        
        // 尝试释放资源并重新创建
        try {
          if (this.avPlayer) {
            await this.avPlayer.release();
            this.avPlayer = null;
          }
        } catch (releaseError) {
          console.error('释放AVPlayer失败:', releaseError);
        }
        
        reject(error);
      }
    });
    
    return this.initPromise;
  }
  
  // 重置播放器
  private async resetPlayer(): Promise<void> {
    try {
      console.info('重置AVPlayer');
      if (this.avPlayer) {
        await this.avPlayer.release();
        this.avPlayer = null;
      }
      await this.initPlayer();
    } catch (error) {
      console.error('重置AVPlayer失败:', error instanceof Error ? error.message : String(error));
    }
  }

  /**
   * 播放音频文件
   * @param audioUrl 音频文件URL
   */
  private async playAudioFile(audioUrl: string): Promise<void> {
    try {
      // 确保播放器已初始化
      console.info('[TtsUtil] 准备初始化播放器');
      await this.initPlayer();
      
      if (!this.avPlayer) {
        console.error('[TtsUtil] 播放器未初始化');
        throw new Error('播放器未初始化');
      }

      console.info('[TtsUtil] 准备播放音频文件:', audioUrl);

      // 停止当前播放
      await this.stopPlayback();

      try {
        console.info('[TtsUtil] 设置音频源:', audioUrl);
        this.avPlayer.url = audioUrl;
        
        console.info('[TtsUtil] 准备播放器');
        await this.avPlayer.prepare();
        
        console.info('[TtsUtil] 开始播放');
        await this.avPlayer.play();
        this.isPlaying = true;
        
        console.info('[TtsUtil] 音频开始播放成功');
      } catch (playError) {
        console.error('[TtsUtil] 播放音频失败:', playError instanceof Error ? playError.message : String(playError));
        throw new Error('播放音频失败: ' + (playError instanceof Error ? playError.message : String(playError)));
      }
    } catch (error) {
      console.error('[TtsUtil] 播放音频文件失败:', error instanceof Error ? error.message : String(error));
      throw new Error('播放音频文件失败: ' + (error instanceof Error ? error.message : String(error)));
    }
  }

  /**
   * 合成并播放短文本(≤150字符)
   * @param text 要合成的文本
   * @param voiceType 音色类型(可选)
   * @param speed 语速(可选)
   * @returns 播放是否成功
   */
  public async speakText(text: string, voiceType?: number, speed?: number): Promise<boolean> {
    if (!text || text.trim().length === 0) {
      console.warn('[TtsUtil] 尝试播放空文本');
      return false;
    }
    
    // 防止重复播放同一文本
    const now = Date.now();
    if (text === this.lastPlayedText && now - this.lastPlayedTime < 3000) {
      console.info('[TtsUtil] 忽略重复播放请求，时间间隔太短');
      return true;
    }
    
    console.info('[TtsUtil] 准备播放文本:', text);
    this.lastPlayedText = text;
    this.lastPlayedTime = now;
    this.currentRetry = 0;
    
    return this.attemptSpeakText(text, voiceType, speed);
  }
  
  /**
   * 尝试播放文本，带重试逻辑
   */
  private async attemptSpeakText(text: string, voiceType?: number, speed?: number): Promise<boolean> {
    try {
      console.info('[TtsUtil] 开始尝试播放文本');
      
      // 确保播放器已初始化
      await this.initPlayer();
      
      // 如果文本长度超过150，使用长文本接口
      if (text.length > 150) {
        console.info('[TtsUtil] 文本长度超过150，使用长文本接口');
        return await this.speakLongText(text, voiceType, speed);
      }

      console.info(`[TtsUtil] 尝试播放文本 (尝试 ${this.currentRetry + 1}/${this.MAX_RETRIES + 1})`);
      
      // 构建请求参数
      const params = new SimpleURLSearchParams();
      params.append('text', text);
      if (voiceType !== undefined) {
        params.append('voiceType', voiceType.toString());
      }
      if (speed !== undefined) {
        params.append('speed', speed.toString());
      }

      const url = `${this.BASE_URL}/api/tts/synthesize`;
      console.info('[TtsUtil] 发送TTS请求:', url);
      console.info('[TtsUtil] 请求参数:', params.toString());
      
      // 发送请求
      const httpRequest = http.createHttp();
      const response = await httpRequest.request(url, {
        method: http.RequestMethod.POST,
        header: {
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        extraData: params.toString(),
        connectTimeout: 10000,
        readTimeout: 10000
      });
      
      console.info('[TtsUtil] 收到响应，状态码:', response.responseCode);
      
      // 处理响应
      if (response.responseCode === 200) {
        const resultText = response.result as string;
        console.info('[TtsUtil] 响应内容:', resultText);
        
        try {
          const result = JSON.parse(resultText) as TtsResponse;
          if (result.success && result.audioUrl) {
            console.info('[TtsUtil] TTS请求成功，音频URL:', result.audioUrl);
            // 播放音频文件
            await this.playAudioFile(result.audioUrl);
            return true;
          } else {
            console.error('[TtsUtil] TTS响应成功但数据无效:', result.message || '未知错误');
            throw new Error(result.message || '语音合成失败');
          }
        } catch (parseError) {
          console.error('[TtsUtil] 解析TTS响应失败:', parseError instanceof Error ? parseError.message : String(parseError));
          throw new Error('解析TTS响应失败: ' + (parseError instanceof Error ? parseError.message : String(parseError)));
        }
      } else {
        console.error('[TtsUtil] TTS请求失败，状态码:', response.responseCode);
        throw new Error(`TTS请求失败，状态码: ${response.responseCode}`);
      }
    } catch (error) {
      console.error('[TtsUtil] 播放文本失败:', error instanceof Error ? error.message : String(error));
      
      // 如果还有重试机会，进行重试
      if (this.currentRetry < this.MAX_RETRIES) {
        this.currentRetry++;
        console.info(`[TtsUtil] 播放失败，将在${this.RETRY_DELAY}ms后进行第${this.currentRetry}次重试`);
        
        await new Promise<void>((resolve) => setTimeout(resolve, this.RETRY_DELAY));
        return this.attemptSpeakText(text, voiceType, speed);
      }
      
      console.error('[TtsUtil] 语音合成失败，已达到最大重试次数');
      return false;
    }
  }

  /**
   * 合成并播放长文本(>150字符)
   * @param text 要合成的文本
   * @param voiceType 音色类型(可选)
   * @param speed 语速(可选)
   * @returns 播放是否成功
   */
  public async speakLongText(text: string, voiceType?: number, speed?: number): Promise<boolean> {
    try {
      // 构建请求参数
      const params = new SimpleURLSearchParams();
      params.append('text', text);
      if (voiceType !== undefined) {
        params.append('voiceType', voiceType.toString());
      }
      if (speed !== undefined) {
        params.append('speed', speed.toString());
      }

      const url = `${this.BASE_URL}/api/tts/synthesize`;
      
      // 显示加载提示
      promptAction.showToast({
        message: '正在生成语音...',
        duration: 2000
      });
      
      console.info('发送长文本TTS请求:', url);
      
      // 发送请求
      const httpRequest = http.createHttp();
      const response = await httpRequest.request(url, {
        method: http.RequestMethod.POST,
        header: {
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        extraData: params.toString(),
        connectTimeout: 30000,
        readTimeout: 30000
      });
      
      // 处理响应
      if (response.responseCode === 200) {
        const resultText = response.result as string;
        try {
          const result = JSON.parse(resultText) as TtsResponse;
          if (result.success && result.audioUrl) {
            console.info('长文本TTS请求成功，准备播放音频');
            // 播放音频文件
            await this.playAudioFile(result.audioUrl);
            return true;
          } else {
            console.error('长文本TTS响应成功但数据无效:', result.message || '未知错误');
          }
        } catch (parseError) {
          console.error('解析长文本TTS响应失败:', parseError instanceof Error ? parseError.message : String(parseError));
        }
      } else {
        console.error('长文本TTS请求失败，状态码:', response.responseCode);
      }
      
      console.error('长文本语音合成失败');
      promptAction.showToast({
        message: '语音合成失败',
        duration: 2000
      });
      return false;
    } catch (error) {
      console.error('长文本语音合成异常:', error instanceof Error ? error.message : String(error));
      promptAction.showToast({
        message: '语音合成发生错误',
        duration: 2000
      });
      return false;
    }
  }
  
  /**
   * 停止当前播放
   */
  public async stopPlayback(): Promise<void> {
    try {
      console.info('[TtsUtil] 停止播放');
      this.isPlaying = false;

      if (this.avPlayer) {
        try {
          // 停止播放
          await this.avPlayer.stop();
          // 释放资源
          await this.avPlayer.release();
          this.avPlayer = null;
          console.info('[TtsUtil] 成功停止播放并释放资源');
        } catch (error) {
          console.error('[TtsUtil] 停止播放时发生错误:', error instanceof Error ? error.message : String(error));
        }
      }

      // 重置状态
      this.lastPlayedText = '';
      this.lastPlayedTime = 0;
      this.currentRetry = 0;
      this.isInitializing = false;
      this.initPromise = null;

      console.info('[TtsUtil] 播放状态已重置');
    } catch (error) {
      console.error('[TtsUtil] 停止播放过程中发生错误:', error instanceof Error ? error.message : String(error));
    }
  }
  
  /**
   * 检查是否正在播放
   */
  public isCurrentlyPlaying(): boolean {
    return this.isPlaying;
  }
  
  /**
   * 播放远程音频文件（直接URL）
   * @param url 远程音频URL
   * @returns 播放是否成功
   */
  public async playRemoteAudio(url: string): Promise<boolean> {
    return new Promise<boolean>((resolve) => {
      try {
        if (!url) {
          console.error('TtsUtil: 远程音频URL为空');
          resolve(false);
          return;
        }

        console.info(`TtsUtil: 开始播放远程音频: ${url}`);
        
        // 直接使用现有的playAudioFile方法播放远程URL
        this.playAudioFile(url).then(() => {
          resolve(true);
        }).catch((error) => {
          console.error(`TtsUtil: 播放远程音频失败: ${error}`);
          resolve(false);
        });
        
        // 设置超时处理
        setTimeout(() => {
          if (!this.isPlaying) {
            console.warn('TtsUtil: 播放远程音频超时');
            resolve(false);
          }
        }, 10000); // 10秒超时
      } catch (error) {
        console.error(`TtsUtil: 播放远程音频异常: ${error}`);
        resolve(false);
      }
    });
  }
} 